/******************************************************************************* * Copyright (c) 2006-2013 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ package org.emftext.language.mecore.resource.mecore.mopp; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EEnumLiteral; import org.eclipse.emf.ecore.EGenericType; import org.eclipse.emf.ecore.EModelElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.ETypeParameter; import org.eclipse.emf.ecore.ETypedElement; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.util.EcoreUtil; import org.emftext.language.mecore.MAnnotation; import org.emftext.language.mecore.MAnnotationEntry; import org.emftext.language.mecore.MClass; import org.emftext.language.mecore.MClassifier; import org.emftext.language.mecore.MComplexMultiplicity; import org.emftext.language.mecore.MDataType; import org.emftext.language.mecore.MEcoreType; import org.emftext.language.mecore.MEnum; import org.emftext.language.mecore.MEnumLiteral; import org.emftext.language.mecore.MFeature; import org.emftext.language.mecore.MModelElement; import org.emftext.language.mecore.MMultiplicity; import org.emftext.language.mecore.MOperation; import org.emftext.language.mecore.MPackage; import org.emftext.language.mecore.MParameter; import org.emftext.language.mecore.MSimpleMultiplicity; import org.emftext.language.mecore.MSimpleMultiplicityValue; import org.emftext.language.mecore.MType; import org.emftext.language.mecore.MTypeArgument; import org.emftext.language.mecore.MTypeParameter; import org.emftext.language.mecore.MTypeReference; import org.emftext.language.mecore.MTypedElement; import org.emftext.language.mecore.MWildcard; import org.emftext.language.mecore.resource.mecore.IMecoreCommand; /** * Converts Mecore models to Ecore models. The wrapper tries to keep the * contents of the previous Ecore model to the extent possible. */ public class MecoreWrapper { private static final EcoreFactory ECORE_FACTORY = EcoreFactory.eINSTANCE; private static final String ANNOTATION_SOURCE = MecoreWrapper.class .getName(); private static final String COMMENT_KEY = "WARNING"; private static final String COMMENT_VALUE = "This element was generated from an .mecore file. Removing this annotation will signal the MinimalEcore builder to keep this element."; private Map<MModelElement, EObject> primaryMapping = new LinkedHashMap<MModelElement, EObject>(); // this mapping is to used to trace validation errors that are detected in // the Ecore model back to the Mecore model private Map<EObject, MModelElement> reverseMapping = new LinkedHashMap<EObject, MModelElement>(); /** * Some steps in the creation of the Ecore model need to be postponed (e.g., * the creation of super type references). We collect these steps in this * list of commands and execute them after the structure of the Ecore model * was created completely. */ private List<IMecoreCommand<Object>> commands = new ArrayList<IMecoreCommand<Object>>(); public EPackage wrapMPackage(MPackage mPackage, EPackage existingEPackage) { if (existingEPackage != null) { primaryMapping.put(mPackage, existingEPackage); } EPackage superPackage = null; if (existingEPackage != null) { existingEPackage.getESuperPackage(); } EPackage ePackage = findOrCreateEPackage(mPackage, superPackage); // set package properties String packageName = mPackage.getName(); if (packageName == null) { ePackage.setName(mPackage.eResource().getURI().fragment()); } else { ePackage.setName(packageName); } ePackage.setNsURI(mPackage.getNamespace()); ePackage.setNsPrefix(mPackage.getName()); // process package contents for (MClassifier mClassifier : mPackage.getContents()) { wrapMClassifier(mClassifier, ePackage); } wrapMAnnotations(mPackage, ePackage); // execute deferred commands for (IMecoreCommand<Object> command : commands) { command.execute(null); } removeObsoleteElements(ePackage); return ePackage; } private void wrapMAnnotations(MModelElement mecoreModelElement, EModelElement ecoreModelElement) { for (MAnnotation annotation: mecoreModelElement.getAnnotations()) { for (MAnnotationEntry entry: annotation.getEntries()) { addAnnotation(ecoreModelElement, annotation.getAnnotationDefinition().getSource(), entry.getKey(), entry.getValue()); } } } private void removeObsoleteElements(EPackage ePackage) { List<EObject> obsoleteElements = new ArrayList<EObject>(); removeObsoleteElements(ePackage, obsoleteElements); for (EObject eObject : obsoleteElements) { EcoreUtil.remove(eObject); } } private void removeObsoleteElements(EObject eObject, List<EObject> obsoleteElements) { // remove elements that have an MEcore annotation, but that are not // present // in the .mecore file anymore for (EObject child : eObject.eContents()) { boolean wasMapped = primaryMapping.values().contains(child); boolean isAnnotation = child instanceof EAnnotation; if (hasAnnotation(child) && !wasMapped && !isAnnotation) { obsoleteElements.add(child); } else { // call method recursively on children removeObsoleteElements(child, obsoleteElements); } } } private void addAnnotation(EModelElement element, String source, String key, String value) { EAnnotation eAnnotation = element.getEAnnotation(source); if (eAnnotation == null) { eAnnotation = ECORE_FACTORY.createEAnnotation(); eAnnotation.setSource(source); element.getEAnnotations().add(eAnnotation); } eAnnotation.getDetails().put(key, value); } private void addAnnotation(EModelElement element, String comment) { EAnnotation eAnnotation = ECORE_FACTORY.createEAnnotation(); // TODO add reverse mapping eAnnotation.setSource(ANNOTATION_SOURCE); eAnnotation.getDetails().put(COMMENT_KEY, comment); element.getEAnnotations().add(eAnnotation); } private boolean hasAnnotation(EObject eObject) { if (eObject instanceof EModelElement) { EModelElement element = (EModelElement) eObject; EAnnotation annotation = element.getEAnnotation(ANNOTATION_SOURCE); return annotation != null; } else { return false; } } private void wrapMClassifier(MClassifier mClassifier, EPackage ePackage) { if (mClassifier instanceof MClass) { wrapMClass((MClass) mClassifier, ePackage); } else if (mClassifier instanceof MEnum) { wrapMEnum((MEnum) mClassifier, ePackage); } } private void wrapMEnum(MEnum mEnum, EPackage ePackage) { EEnum eEnum = findOrCreateEEnum(mEnum, ePackage); eEnum.setName(mEnum.getName()); int count = 0; for (MEnumLiteral literal : mEnum.getLiterals()) { wrapMEnumLiteral(literal, eEnum, count++); } wrapMAnnotations(mEnum, eEnum); primaryMapping.put(mEnum, eEnum); } private void wrapMEnumLiteral(MEnumLiteral literal, EEnum existingEEnum, int count) { EEnumLiteral eEnumLiteral = findOrCreateEEnumLiteral(literal, existingEEnum); eEnumLiteral.setName(literal.getName()); eEnumLiteral.setLiteral(literal.getLiteral()); eEnumLiteral.setValue(count); wrapMAnnotations(literal, eEnumLiteral); primaryMapping.put(literal, eEnumLiteral); } private void wrapMClass(final MClass mClass, EPackage ePackage) { final EClass eClass = findOrCreateEClass(mClass, ePackage); primaryMapping.put(mClass, eClass); eClass.getESuperTypes().clear(); eClass.setName(mClass.getName()); boolean isInterface = mClass.isInterface(); // interfaces must be abstract eClass.setAbstract(isInterface || mClass.isAbstract()); eClass.setInterface(isInterface); // handle features for (MFeature mFeature : mClass.getFeatures()) { wrapMFeature(mFeature, eClass); } // handle operations for (MOperation mOperation : mClass.getOperations()) { wrapMOperation(mOperation, eClass); } wrapMAnnotations(mClass, eClass); // handle type parameters addTypeParameters(mClass, eClass); // handle super types wrapMSuperTypeReferences(mClass, eClass); } private void wrapMSuperTypeReferences(final MClass mClass, final EClass eClass) { commands.add(new IMecoreCommand<Object>() { public boolean execute(Object context) { // add local super types for (MTypeReference supertypeRef : mClass .getSuperTypeReferences()) { wrapMSuperTypeReference(eClass, supertypeRef); } return true; } }); } private EClass getSuperType(MTypeReference supertypeRef) { MType mSupertype = supertypeRef.getType(); if (mSupertype != null) { return (EClass) primaryMapping.get(mSupertype); } /* EClass eSuperType = supertypeRef.getEType(); if (eSuperType != null) { return eSuperType; } */ return null; } private void wrapMFeature(MFeature mFeature, EClass existingEClass) { EStructuralFeature eFeature; MTypeReference mTypeRef = mFeature.getType(); if (mTypeRef == null) { return; } final MType mType = mTypeRef.getType(); if (mType == null) { return; } if (mType instanceof MClass) { eFeature = createReference(mFeature, existingEClass, mTypeRef); } else if (mType instanceof MDataType) { eFeature = createAttribute(mFeature, existingEClass, mTypeRef); } else if (mType instanceof MEnum) { final EAttribute eAttribute = findOrCreateEAttribute(mFeature, existingEClass); commands.add(new IMecoreCommand<Object>() { public boolean execute(Object context) { eAttribute.setEType((EEnum) primaryMapping.get(mType)); return true; } }); eFeature = eAttribute; } else if (mType instanceof MEcoreType) { eFeature = createReference(mFeature, existingEClass, mTypeRef); } else if (mType instanceof MTypeParameter) { eFeature = createReference(mFeature, existingEClass, mTypeRef); } else { throw new RuntimeException("Found unknown subtype of MType: " + mType.eClass().getName()); } setMultiplicity(mFeature, eFeature); wrapMAnnotations(mFeature, eFeature); primaryMapping.put(mFeature, eFeature); eFeature.setName(mFeature.getName()); } private EStructuralFeature createAttribute(MFeature mFeature, EClass existingEClass, MTypeReference mTypeRef) { // primitive type, create attribute EAttribute eAttribute = findOrCreateEAttribute(mFeature, existingEClass); setType(eAttribute, mTypeRef); return eAttribute; } private void wrapMOperation(MOperation mOperation, EClass existingEClass) { final MTypeReference mTypeRef = mOperation.getType(); if (mTypeRef == null) { return; } final EOperation eOperation = findOrCreateEOperation(mOperation, existingEClass); addTypeParameters(mOperation, eOperation); // handle parameters for (MParameter mParameter : mOperation.getParameters()) { wrapMParameter(mParameter, eOperation); } commands.add(new IMecoreCommand<Object>() { public boolean execute(Object context) { setType(eOperation, mTypeRef); return true; } }); setMultiplicity(mOperation, eOperation); wrapMAnnotations(mOperation, eOperation); primaryMapping.put(mOperation, eOperation); eOperation.setName(mOperation.getName()); } private void addTypeParameters(MOperation mOperation, EOperation eOperation) { List<MTypeParameter> typeParameters = mOperation.getTypeParameters(); for (MTypeParameter typeParameter : typeParameters) { findOrCreateETypeParameter(eOperation, typeParameter); } } private void addTypeParameters(MClass mClass, EClass eClass) { List<MTypeParameter> typeParameters = mClass.getTypeParameters(); for (MTypeParameter typeParameter : typeParameters) { findOrCreateETypeParameter(eClass, typeParameter); } } private ETypeParameter findOrCreateETypeParameter(EOperation eOperation, MTypeParameter typeParameter) { List<ETypeParameter> eTypeParameters = eOperation.getETypeParameters(); return findOrCreateTypeParameter(typeParameter, eTypeParameters); } private ETypeParameter findOrCreateETypeParameter(EClass eClass, MTypeParameter typeParameter) { List<ETypeParameter> eTypeParameters = eClass.getETypeParameters(); return findOrCreateTypeParameter(typeParameter, eTypeParameters); } private ETypeParameter findOrCreateTypeParameter( final MTypeParameter typeParameter, List<ETypeParameter> eTypeParameters) { String mName = typeParameter.getName(); for (ETypeParameter eTypeParameter : eTypeParameters) { String eName = eTypeParameter.getName(); if (eName != null && eName.equals(mName)) { primaryMapping.put(typeParameter, eTypeParameter); return eTypeParameter; } } final ETypeParameter newETypeParameter = ECORE_FACTORY .createETypeParameter(); reverseMapping.put(newETypeParameter, typeParameter); newETypeParameter.setName(mName); // set type bounds commands.add(new IMecoreCommand<Object>() { @Override public boolean execute(Object context) { setTypeBound(typeParameter, newETypeParameter); return true; } }); eTypeParameters.add(newETypeParameter); // TODO this mapping must consider scoping of type parameters primaryMapping.put(typeParameter, newETypeParameter); return newETypeParameter; } private void setTypeBound(MTypeParameter mTypeParameter, ETypeParameter eTypeParameter) { MTypeReference lowerBound = mTypeParameter.getLowerBound(); if (lowerBound == null) { return; } MType lowerBoundType = lowerBound.getType(); EGenericType eLowerBound = ECORE_FACTORY.createEGenericType(); reverseMapping.put(eLowerBound, mTypeParameter); eLowerBound.setEClassifier(getEType(lowerBoundType)); eTypeParameter.getEBounds().add(eLowerBound); } private void wrapMParameter(MParameter mParameter, EOperation existingOperation) { final MTypeReference mTypeRef = mParameter.getType(); if (mTypeRef == null) { return; } final EParameter eParameter = findOrCreateEParameter(mParameter, existingOperation); commands.add(new IMecoreCommand<Object>() { public boolean execute(Object context) { setType(eParameter, mTypeRef); return true; } }); setMultiplicity(mParameter, eParameter); primaryMapping.put(mParameter, eParameter); eParameter.setName(mParameter.getName()); } private EStructuralFeature createReference(final MFeature mFeature, EClass eClass, final MTypeReference mTypeRef) { // complex type, create reference final EReference eReference = findOrCreateEReference(mFeature, eClass); commands.add(new IMecoreCommand<Object>() { public boolean execute(Object context) { setType(eReference, mTypeRef); MFeature opposite = mFeature.getOpposite(); if (opposite != null) { eReference.setEOpposite((EReference) primaryMapping .get(opposite)); } else { eReference.setEOpposite(null); } return true; } }); eReference.setContainment(!mFeature.isNcReference()); return eReference; } private void setMultiplicity(MTypedElement mElement, ETypedElement eElement) { MMultiplicity multiplicity = mElement.getMultiplicity(); if (multiplicity instanceof MSimpleMultiplicity) { MSimpleMultiplicity simpleMultiplicity = (MSimpleMultiplicity) multiplicity; MSimpleMultiplicityValue value = simpleMultiplicity.getValue(); if (value == MSimpleMultiplicityValue.STAR) { setBounds(eElement, 0, -1); } else if (value == MSimpleMultiplicityValue.PLUS) { setBounds(eElement, 1, -1); } else if (value == MSimpleMultiplicityValue.OPTIONAL) { setBounds(eElement, 0, 1); } else { setBounds(eElement, 1, 1); } } else if (multiplicity instanceof MComplexMultiplicity) { MComplexMultiplicity complexMultiplicity = (MComplexMultiplicity) multiplicity; eElement.setLowerBound(complexMultiplicity.getLowerBound()); eElement.setUpperBound(complexMultiplicity.getUpperBound()); } else if (multiplicity == null) { setBounds(eElement, 1, 1); } } private void setBounds(ETypedElement element, int lower, int upper) { element.setLowerBound(lower); element.setUpperBound(upper); } private EPackage findOrCreateEPackage(MPackage mPackage, EPackage existingSuperPackage) { if (primaryMapping.containsKey(mPackage)) { return (EPackage) primaryMapping.get(mPackage); } if (existingSuperPackage != null) { List<EPackage> existingSubPackages = existingSuperPackage .getESubpackages(); for (EPackage existingSubPackage : existingSubPackages) { if (mPackage.getName().equals(existingSubPackage.getName())) { primaryMapping.put(mPackage, existingSubPackage); return (EPackage) existingSubPackage; } } } // if we can't find an existing EPackage, we need to create a fresh one EPackage ePackage = ECORE_FACTORY.createEPackage(); reverseMapping.put(ePackage, mPackage); addAnnotation(ePackage, COMMENT_VALUE); if (existingSuperPackage != null) { existingSuperPackage.getESubpackages().add(ePackage); } primaryMapping.put(mPackage, ePackage); return ePackage; } private EClass findOrCreateEClass(MClass mClass, EPackage ePackage) { if (primaryMapping.containsKey(mClass)) { return (EClass) primaryMapping.get(mClass); } EClassifier existingEClassifier = ePackage.getEClassifier(mClass .getName()); if (existingEClassifier != null && existingEClassifier instanceof EClass) { primaryMapping.put(mClass, existingEClassifier); return (EClass) existingEClassifier; } // if we can't find an existing EClass, we need to create a fresh one EClass eClass = ECORE_FACTORY.createEClass(); reverseMapping.put(eClass, mClass); addAnnotation(eClass, COMMENT_VALUE); ePackage.getEClassifiers().add(eClass); primaryMapping.put(mClass, eClass); return eClass; } private EEnum findOrCreateEEnum(MEnum mEnum, EPackage ePackage) { if (primaryMapping.containsKey(mEnum)) { return (EEnum) primaryMapping.get(mEnum); } EClassifier existingEClassifier = ePackage.getEClassifier(mEnum .getName()); if (existingEClassifier != null && existingEClassifier instanceof EEnum) { primaryMapping.put(mEnum, existingEClassifier); return (EEnum) existingEClassifier; } // if we can't find an existing EEnum, we need to create a fresh one EEnum eEnum = ECORE_FACTORY.createEEnum(); reverseMapping.put(eEnum, mEnum); addAnnotation(eEnum, COMMENT_VALUE); ePackage.getEClassifiers().add(eEnum); primaryMapping.put(mEnum, eEnum); return eEnum; } private EEnumLiteral findOrCreateEEnumLiteral(MEnumLiteral mEnumLiteral, EEnum existingEnum) { if (primaryMapping.containsKey(mEnumLiteral)) { return (EEnumLiteral) primaryMapping.get(mEnumLiteral); } EEnumLiteral existingEEnumLiteral = existingEnum .getEEnumLiteral(mEnumLiteral.getName()); if (existingEEnumLiteral != null) { primaryMapping.put(mEnumLiteral, existingEEnumLiteral); return existingEEnumLiteral; } // if we can't find an existing EEnumLiteral, we need to create a fresh // one EEnumLiteral eEnumLiteral = ECORE_FACTORY.createEEnumLiteral(); reverseMapping.put(eEnumLiteral, mEnumLiteral); addAnnotation(eEnumLiteral, COMMENT_VALUE); existingEnum.getELiterals().add(eEnumLiteral); primaryMapping.put(mEnumLiteral, eEnumLiteral); return eEnumLiteral; } private EAttribute findOrCreateEAttribute(MFeature mFeature, EClass existingEClass) { if (primaryMapping.containsKey(mFeature)) { return (EAttribute) primaryMapping.get(mFeature); } EStructuralFeature existingFeature = existingEClass .getEStructuralFeature(mFeature.getName()); if (existingFeature != null && existingFeature instanceof EAttribute) { primaryMapping.put(mFeature, existingFeature); return (EAttribute) existingFeature; } // if we can't find an existing EAttribute, we need to create a fresh // one EAttribute eAttribute = ECORE_FACTORY.createEAttribute(); reverseMapping.put(eAttribute, mFeature); addAnnotation(eAttribute, COMMENT_VALUE); existingEClass.getEStructuralFeatures().add(eAttribute); primaryMapping.put(mFeature, eAttribute); return eAttribute; } private EReference findOrCreateEReference(MFeature mFeature, EClass existingEClass) { if (primaryMapping.containsKey(mFeature)) { return (EReference) primaryMapping.get(mFeature); } EStructuralFeature existingFeature = existingEClass .getEStructuralFeature(mFeature.getName()); if (existingFeature != null && existingFeature instanceof EReference) { primaryMapping.put(mFeature, existingFeature); return (EReference) existingFeature; } // if we can't find an existing EReference, we need to create a fresh // one EReference eReference = ECORE_FACTORY.createEReference(); reverseMapping.put(eReference, mFeature); addAnnotation(eReference, COMMENT_VALUE); existingEClass.getEStructuralFeatures().add(eReference); primaryMapping.put(mFeature, eReference); return eReference; } private EOperation findOrCreateEOperation(MOperation mOperation, EClass existingEClass) { if (primaryMapping.containsKey(mOperation)) { return (EOperation) primaryMapping.get(mOperation); } EOperation existingOperation = null; for (EOperation operation : existingEClass.getEOperations()) { String name = operation.getName(); if (name != null && name.equals(mOperation.getName())) { // TODO check parameter types and return type existingOperation = operation; break; } } if (existingOperation != null && existingOperation instanceof EOperation) { primaryMapping.put(mOperation, existingOperation); return (EOperation) existingOperation; } // if we can't find an existing EOperation, we need to create a fresh // one EOperation eOperation = ECORE_FACTORY.createEOperation(); reverseMapping.put(eOperation, mOperation); addAnnotation(eOperation, COMMENT_VALUE); existingEClass.getEOperations().add(eOperation); primaryMapping.put(mOperation, eOperation); return eOperation; } private EParameter findOrCreateEParameter(MParameter mParameter, EOperation existingEOperation) { if (primaryMapping.containsKey(mParameter)) { return (EParameter) primaryMapping.get(mParameter); } EParameter existingParameter = null; for (EParameter parameter : existingEOperation.getEParameters()) { String name = parameter.getName(); if (name != null && name.equals(mParameter.getName())) { // TODO check parameter types and return type existingParameter = parameter; break; } } if (existingParameter != null && existingParameter instanceof EParameter) { primaryMapping.put(mParameter, existingParameter); return (EParameter) existingParameter; } // if we can't find an existing EParameter, we need to create a fresh // one EParameter eParameter = ECORE_FACTORY.createEParameter(); reverseMapping.put(eParameter, mParameter); addAnnotation(eParameter, COMMENT_VALUE); existingEOperation.getEParameters().add(eParameter); primaryMapping.put(mParameter, eParameter); return eParameter; } public Map<EObject, MModelElement> getReverseMapping() { return reverseMapping; } private EClassifier getEType(MType mType) { EClassifier eType = null; if (mType instanceof MEcoreType) { MEcoreType mEcoreType = (MEcoreType) mType; eType = mEcoreType.getEcoreType(); } else if (mType instanceof MDataType) { MDataType mDataType = (MDataType) mType; eType = mDataType.getEDataType(); } else if (mType instanceof MTypeParameter) { // requires a generic type } else { EClass eClass = (EClass) primaryMapping.get(mType); eType = eClass; } return eType; } private EGenericType getGenericEType(MType mType) { if (mType instanceof MTypeParameter) { MTypeParameter mTypeParameter = (MTypeParameter) mType; EGenericType eGenericType = createEGenericTypeParameter(mTypeParameter); return eGenericType; } else { // requires a normal type return null; } } private void setType(ETypedElement eTypedElement, MTypeReference mTypeRef) { List<MTypeArgument> mTypeArguments = mTypeRef.getTypeArguments(); MType mType = mTypeRef.getType(); if (mType == null) { return; } EClassifier eType = getEType(mType); EGenericType eGenericType = getGenericEType(mType); if (mTypeArguments.isEmpty()) { if (eType != null) { eTypedElement.setEType(eType); } if (eGenericType != null) { eTypedElement.setEGenericType(eGenericType); } } else { if (eGenericType == null) { eGenericType = ECORE_FACTORY.createEGenericType(); reverseMapping.put(eGenericType, mType); } if (eType != null) { eGenericType.setEClassifier(eType); } List<EGenericType> eTypeArguments = eGenericType .getETypeArguments(); for (MTypeArgument mTypeArgument : mTypeArguments) { if (mTypeArgument instanceof MTypeReference) { MTypeReference mConcreteTypeReference = (MTypeReference) mTypeArgument; MType nextMType = mConcreteTypeReference.getType(); eTypeArguments.add(createEGenericTypeParameter(nextMType)); } else if (mTypeArgument instanceof MWildcard) { // TODO? System.out.println("MecoreWrapper.setType() found wildcard"); eTypeArguments.add(ECORE_FACTORY.createEGenericType()); } } eTypedElement.setEGenericType(eGenericType); } } private EGenericType createEGenericTypeParameter(MType mType) { EGenericType genericType = ECORE_FACTORY.createEGenericType(); reverseMapping.put(genericType, mType); ETypeParameter eTypeParameter = (ETypeParameter) primaryMapping .get(mType); genericType.setETypeParameter(eTypeParameter); return genericType; } private void wrapMSuperTypeReference(final EClass eClass, MTypeReference supertypeRef) { List<EClass> eSuperTypes = eClass.getESuperTypes(); List<EGenericType> eGenericSuperTypes = eClass.getEGenericSuperTypes(); EClass eSuperType = getSuperType(supertypeRef); if (eSuperType == null) { return; } List<MTypeArgument> mTypeArguments = supertypeRef.getTypeArguments(); if (mTypeArguments.isEmpty()) { // this is a non-generic super type if (!eSuperTypes.contains(eSuperType)) { eSuperTypes.add(eSuperType); } } else { EGenericType eGenericSuperType = ECORE_FACTORY .createEGenericType(); reverseMapping.put(eGenericSuperType, supertypeRef); eGenericSuperType.setEClassifier(eSuperType); eGenericSuperTypes.add(eGenericSuperType); for (MTypeArgument mTypeArgument : mTypeArguments) { if (mTypeArgument instanceof MTypeReference) { MTypeReference mTypeReference = (MTypeReference) mTypeArgument; MType nextMType = mTypeReference.getType(); EGenericType eTypeArgument = ECORE_FACTORY .createEGenericType(); reverseMapping.put(eTypeArgument, supertypeRef); EClassifier eType = getEType(nextMType); eTypeArgument.setEClassifier(eType); eGenericSuperType.getETypeArguments().add(eTypeArgument); } } } } }